package com.itguigu.advice;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 切入点表达式的讲解
 */
//@Aspect
//@Component
//@Order(10) // 优先级 值越小优先级越高
public class PointcutExpression {
    /**
     *TODO 切入点表达式
     *   固定语法 execution(访问权限符 返回值类型 包的位置 类名.方法名(参数列表))
     *   1.访问权限符
     *       public / private / protected / *
     *   2.返回值类型
     *       String / int / void / *(不考虑修饰符和返回值时候使用)
     *   3.包的位置
     *       具体包：com.itguigu.service.impl
     *       单层模糊：com.itguigu.service.impl.*
     *       多层模糊：com..impl
     *       细节：..不能开头
     *       找到所有impl包: *..impl
     *   4.类名
     *       具体类名：CalculatorImpl
     *       模糊：*Impl
     *   5.方法名：语法和类名一致
     *   6.参数列表
     *       无参：()
     *       有具体参数：(String,int)
     *       模糊参数：(..)
     *       模糊：(String,..)String后面有没有无所谓
     *            (..,int)int前面有没有无所谓
     */

    /**
     * TODO:切点表达式的提取
     *  一：当前类中提取
     *       1.创建一个空方法
     *       2.在方法上使用注解 @Pointcut("表达式")
     *       3.在需要增强的方法上使用注解 @Before("方法名")
     *  二：创建一个存储切点的类
     *       1.单独维护切点表达式
     *       2.其他类中的切点方法 类的全限定符.方法名
     */

    @Pointcut("execution(* com..impl.*.*(..))")
    public void pc() {
    }

    @Before("pc()")
    public void before() {
        System.out.println("方法开始了");
    }

    @After("com.itguigu.pointcut.mypointcut.pc1()")
    public void after() {
        System.out.println("方法结束了");
    }

    @AfterThrowing(value = "com.itguigu.pointcut.mypointcut.pc2()", throwing = "e")
    public void afterThrowing(JoinPoint point, Throwable e) {
        System.out.println(point.getSignature().getName() + ":出现异常了" + e.getMessage());
    }
}
